#!/usr/bin/env python
# -*- coding: utf-8 -*-

NAME=u'跟花'
CONF=dict(
    #玩家-牌组数对
    player_cards=[[4, 1], [4, 2]], 
    #基牌总数
    cardBases=[2, 3], 
)

HELP=u'''　　　　　　　　　　　　　　　跟　　花

游戏简介：

　　请您按数字的大小或花色接下去。一开始必须先出方块2。

　　在数字相同的情况下，梅花接方块、红桃接梅花、黑桃接红桃、方块接黑桃，如此循环；当花色相同时，按2、3、4、5、6、7、8、9、10、J、Q、K、A、2、3、4、5．．．如此循环接下去。

　　大王和小王是特殊的牌，在您没有牌接上的时候就可以用，大王>小王。

'''

import general
from server import *
from client import *

#基数牌，游戏开始必须出的牌
baseCards=[Card(DIAMOND, TWO), Card(DIAMOND, THREE)]

def getNextCardIds(cardid):
    '''公共方法，寻找下一可接的牌，按规则为：相同花色数字增1或相同数字花色增1的牌'''
    if cardid==BJOKER:
        return [RJOKER]
    elif cardid==RJOKER:
        return []
    card=Card(cardid)
    a=Card(card.suit, (card.face+1)%13)
    b=Card((card.suit+1)%4, card.face)
    return [a.id, b.id]

class Game(general.Game):
    '''测试游戏类，跟花'''
    def __init__(self):
        super(Game, self).__init__()
        
        #游戏模块名称
        self.moduleName='GenHua'
        #游戏名称
        self.name=NAME
    
    def setCardOrder(self, base=2):
        '''设置排序'''
        order=range(13)
        for i in range(base-1):
            c=order.pop()
            order.insert(0, c)
        order1=[i+100 for i in order]
        order2=[i+200 for i in order]
        order3=[i+300 for i in order]
        order=order+order1+order2+order3+[400, 401]
        self.cardOrder=order
    
    def configure(self):
        '''追加设置'''
        super(Game, self).configure()
        #设置基数牌
        bcIndex=CONF['cardBases'].index(self.cardBase)
        self.baseCard=baseCards[bcIndex]
        #设置牌序
        self.setCardOrder(self.cardBase)
        #设置牌堆
        self.table.setPileCards(range(54)*self.cardPack)
        #设置积分盒
        self.table.fillScoreBox([0 for i in range(self.playerCount)])

    def calcScore(self):
        '''计算玩家积分'''
        #这里只是简单累计牌数
        playerCardCount=[len(player.cardList) for player in self.players]
        for i in range(len(playerCardCount)):
            self.scoreBox[i]+=playerCardCount[i]

    def play(self):
        '''打牌'''
        #设置首轮最先出牌者为含有基数牌的玩家
        if self.round==1:
            for player in self.players:
                if self.baseCard.id in player.cardList:
                    self.setMarkPlayerId(player)
                    break
        super(Game, self).play()

    def judge(self, player, data):
        '''出牌有效判定'''
        if len(data)>1:
            #每次出牌数只能1张
            return UNDO
        if self.markPlayerId==player.info['id']:
            #上次被标记的是自己，表示这轮没人跟牌，允许任意出（不允许空），首轮有基数牌要先出
            if not data:
                return UNDO
            cardid=data[0]
            if self.round==1 and (cardid!=self.baseCard.id) and (self.baseCard.id in player.cardList):
                return UNDO
            return OK
        if not data:
            #不出牌，允许
            return OK

        cardid=data[0]
        if cardid==self.baseCard.id and self.markPlayerId==player.info['id']:
            #首牌为基数牌，允许
            return OK
        
        #取得上次被标记玩家出的牌（大牌）
        mcards=self.outList[self.markPlayerId]
        mcard=mcards[0]
        nextcardids=getNextCardIds(mcard)
        
        #允许的常规牌
        rinte=set(nextcardids)&set(player.cardList+data)
        if rinte:
            if cardid in rinte:
                #有规则允许的牌（常规牌），出完后标记该玩家
                self.setMarkPlayerId(player)
                return OK
            else:
                return UNDO
        else:
            #没有常规牌，看是否有特殊牌
            sinte=set(SPECIAL)&set(player.cardList+data)
            if cardid in sinte:
                #有特殊牌，且大，出完后标记该玩家
                if cardid>mcard:
                    self.setMarkPlayerId(player)
                    return OK
                else:
                    return UNDO
            else:
                return UNDO


class AI(general.AI):
    '''跟花游戏的AI'''
    def __init__(self):
        super(AI, self).__init__()
        
    def initData(self):
        '''初始化游戏数据'''
        #获取基数牌
        cardBase=self.player.gameData['cardBase']
        bcIndex=CONF['cardBases'].index(cardBase)
        self.baseCard=baseCards[bcIndex]
        
    def playCard(self):
        '''实现出牌提示逻辑，这里是尽量出可出的牌'''
        markPlayerId=self.player.gameData['markPlayerId']
        round=self.player.gameData['round']
        if markPlayerId==self.player.info['id']:
            if round==1 and (self.baseCard.id in self.player.cardList):
                #首轮有基数牌必出
                return [self.baseCard.id]
            
            #上次被标记的是自己（大），此次任意出牌
            return [random.choice(self.player.cardList)]
        
        #取得上次被标记玩家出的牌（大牌）
        outList=self.player.gameData['outList']
        mcards=outList[markPlayerId]
        mcard=mcards[0]
        #获取可出的牌
        nextcardids=getNextCardIds(mcard)
        rinte=set(nextcardids)&set(self.player.cardList)
        if rinte:
            #有常规牌可出
            return [rinte.pop()]
        #无常规牌
        sinte=set(SPECIAL)&set(self.player.cardList)
        if sinte:
            #但有特殊牌，选大的出
            for cid in sinte:
                if cid>mcard:
                    return [cid]

        #这时无牌可出
        return []


